﻿#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QSettings>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
  ,m_iCounter(0)
  ,m_index(0)
  ,m_bRunStatus(false)
  ,m_dStep(1)
{
    ui->setupUi(this);

    m_lastFolder = QCoreApplication::applicationDirPath();

    InitModel();

    UiConnect();
    SerialPortConnect();
    m_status << "Unknown"
                 << "Idle"
                 << "Alarm"
                 << "Run"
                 << "Home"
                 << "Hold:0"
                 << "Hold:1"
                 << "Queue"
                 << "Check"
                 << "Door"                     // TODO: Update "Door" state
                 << "Jog";

    gcode_ok = false;

    InitSettings();

    InitLoadImage();

    InitVideo();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::InitSettings()
{
    QString settingsFileName = qApp->applicationDirPath() + "/settings.ini";
    QSettings set(settingsFileName, QSettings::IniFormat);
    set.setIniCodec("UTF-8");

    m_szGCodeProtName = set.value("GCodeProt").toString();
    m_szCmdProtName = set.value("CmdProt").toString();
    m_iGCodeProtBaud = set.value("GCodeProtBaud").toInt();
    m_iCmdProtBaud = set.value("CmdProtBaud").toInt();
    m_szAutoCommadFile = set.value("AutoCommadFile").toString();
    m_dStep = set.value("StepSize").toInt();

}


void MainWindow::UiConnect()
{
    //定时器
    connect(&m_timer,SIGNAL(timeout()),this,SLOT(OnLcdTimerSlot()));
    m_timer.start(4000);

    //坐标点动
    connect(ui->toolButton_XPlus,SIGNAL(clicked()),this,SLOT(BtnXplusClickedSlot()));
    connect(ui->toolButton_XMinus,SIGNAL(clicked()),this,SLOT(BtnXminusClickedSlot()));
    connect(ui->toolButton_YPlus,SIGNAL(clicked()),this,SLOT(BtnYplusClickedSlot()));
    connect(ui->toolButton_YMinus,SIGNAL(clicked()),this,SLOT(BtnYminusClickedSlot()));
    connect(ui->toolButton_ZPlus,SIGNAL(clicked()),this,SLOT(BtnZplusClickedSlot()));
    connect(ui->toolButton_ZMinus,SIGNAL(clicked()),this,SLOT(BtnZminusClickedSlot()));

    //文件

    connect(ui->pushButton_modify,SIGNAL(clicked()),this,SLOT(BtnModifyCoordSlot()));
    connect(ui->pushButton_openfile,SIGNAL(clicked()),this,SLOT(BtnOpenFileSlot()));
    connect(ui->pushButton_save,SIGNAL(clicked()),this,SLOT(BtnSaveCoordSlot()));


    //lcd
    connect(ui->pushButton_counterZero,SIGNAL(clicked()),this,SLOT(BtnCounterZeroClickedSlot()));

    //tableview
    connect(ui->tableView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onTableClicked(const QModelIndex &)));


    connect(ui->pushButton_simulated,SIGNAL(clicked()),this,SLOT(BtnSimulatedClickedSlot()));
    connect(ui->buttonGroup,SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(OnModeButtonClicked(QAbstractButton*)));
    connect(ui->pushButton_pause,SIGNAL(clicked()),this,SLOT(BtnPauseButtonClickedSlot()));


}

void MainWindow::SerialPortConnect()
{

}




void MainWindow::InitModel()
{
    m_pModel = new QStandardItemModel(this);
    m_pModel->setColumnCount(5);
    m_pModel->setHeaderData(0,Qt::Horizontal, "M码");
    m_pModel->setHeaderData(1,Qt::Horizontal, "G码");
    m_pModel->setHeaderData(2,Qt::Horizontal, "X坐标");
    m_pModel->setHeaderData(3,Qt::Horizontal, "Y坐标");
    m_pModel->setHeaderData(4,Qt::Horizontal, "Z坐标");

    ui->tableView->setModel(m_pModel);

}

void MainWindow::loadFile(QString fileName)
{
    QFile file(fileName);

    if (!file.open(QIODevice::Text |QIODevice::ReadOnly))
    {
        QMessageBox::critical(this, this->windowTitle(), tr("Can't open file:\n") + fileName);
        return;
    }

    // Set filename
    ui->lineEdit_filename->setText(fileName);

    // Prepare text stream
    QTextStream textStream(&file);

    // Read lines
    QList<QString> data;
    while (!textStream.atEnd()) data.append(textStream.readLine());

    // Load lines
    loadFileData(data);

    file.close();
}

void MainWindow::loadFileData(QList<QString> data)
{
    m_commandList.clear();
    m_index = 0;

    m_pModel->removeRows(0,m_pModel->rowCount());

    m_pModel->setRowCount(data.count());
    for(int i = 0;i<data.count();i++)
    {
       QString str = data[i];
       QStringList strlist = str.split(" ");

       m_commandList.append(str.remove(QRegExp("\\s")));

       for(int j = 0; j<strlist.count();j++)
       {
           if(strlist[j] == "")
           {
               continue;
           }
           QStandardItem *item = new QStandardItem(strlist[j]);
           m_pModel->setItem(i,j,item);
       }

    }


}

void MainWindow::SendCommanLoop()
{

    SendGcode("$J=" + m_commandList[m_index]);
    m_index ++;

   int count = m_commandList.count();
   if(m_index == count)
   {
        m_index = 0;
   }

}

/**********************************************************************************/
void MainWindow::BtnXplusClickedSlot()
{
    QString command ="";
    double x = m_dStep * 1;
    command = QString("G21G91X%1Y0.000Z0.000").arg(QString::number(x,'g',3));
    SendGcode("$J=" + command);

    ChangePosition(1,0,0);

}

void MainWindow::BtnXminusClickedSlot()
{
    QString command ="";
    double x = m_dStep * -1;
    command = QString("G21G91X%1Y0.000Z0.000").arg(QString::number(x,'g',3));
    SendGcode("$J=" + command);

       ChangePosition(-1,0,0);
}

void MainWindow::BtnYplusClickedSlot()
{
    QString command ="";
    double y = m_dStep * 1;
    command = QString("G21G91X0.000Y%1Z0.000").arg(QString::number(y,'g',3));
    SendGcode("$J=" + command);

       ChangePosition(0,1,0);
}

void MainWindow::BtnYminusClickedSlot()
{
    QString command ="";
    double y = m_dStep * -1;
    command = QString("G21G91X0.000Y%1Z0.000").arg(QString::number(y,'g',3));
    SendGcode("$J=" + command);

       ChangePosition(0,-1,0);
}

void MainWindow::BtnZplusClickedSlot()
{
    QString command ="";
    double z = m_dStep * 1;
    command = QString("G21G91X0.000Y0.000Z%1").arg(QString::number(z,'g',3));
    //SendGcode("$J=" + command);

    ChangePosition(0,0,1);
}

void MainWindow::BtnZminusClickedSlot()
{
    QString command ="";
    double z = m_dStep * -1;
    command = QString("G21G91X0.000Y0.000Z%1").arg(QString::number(z,'g',3));
    //SendGcode("$J=" + command);
    ChangePosition(0,0,-1);
}

/**********************************************************************************/

/**********************************************************************************/
void MainWindow::BtnCounterZeroClickedSlot()
{
    m_iCounter = 0;
    OnCounterChangedSlot(m_iCounter);
}

void MainWindow::OnLcdTimerSlot()
{
  if(m_iCounter == MAX_COUNTER)
  {
      m_iCounter = 1;
  }
  OnCounterChangedSlot(m_iCounter++);


  //TODO::cs
  if(m_bAutoMode && m_bRunStatus)
  {
     BtnSimulatedClickedSlot();
  }

}

void MainWindow::OnCounterChangedSlot(int num)
{
    ui->lcdNumber->display(num);
}

/**********************************************************************************/


/**********************************************************************************/
void MainWindow::BtnOpenFileSlot()
{
    QString fileName  = QFileDialog::getOpenFileName(this, tr("Open"), m_lastFolder,
                               tr("G-Code files (*.nc *.ncc *.ngc *.tap *.txt);;All files (*.*)"));

    if (!fileName.isEmpty()) m_lastFolder = fileName.left(fileName.lastIndexOf(QRegExp("[/\\\\]+")));

    if (fileName != "")
    {
        loadFile(fileName);
    }
}

void MainWindow::BtnModifyCoordSlot()
{
    double x = ui->doubleSpinBox_X->value();
    double y = ui->doubleSpinBox_Y->value();
    double z = ui->doubleSpinBox_Z->value();

    int row =  ui->tableView->currentIndex().row();

    QStandardItem *item = m_pModel->item(row,2);
    item->setText("X" + QString::number(x,'f',4));

    item = m_pModel->item(row,3);
    item->setText("Y" + QString::number(y,'f',4));

    item = m_pModel->item(row,4);
    item->setText("Z" + QString::number(z,'f',4));

    //emit m_pModel->dataChanged(m_pModel->index(row,2),m_pModel->index(row,4));

}


void MainWindow::BtnSaveCoordSlot()
{

   QString fileName = (QFileDialog::getSaveFileName(this, tr("Save file as"), m_lastFolder, tr("G-Code files (*.nc *.ncc *.ngc *.tap *.txt)")));
   if (!fileName.isEmpty())
   {
       m_lastFolder = fileName.left(fileName.lastIndexOf(QRegExp("[/\\\\]+")));
       QFile file(fileName);
       if (!file.open(QIODevice::Text |QIODevice::WriteOnly))
       {
           return;
       }
       QTextStream textStream(&file);

       m_commandList.clear();
       m_index = 0;


       int rowCount = m_pModel->rowCount();
       for(int i = 0;i<rowCount;i++)
       {
           QString text = "";

           QModelIndex dIndex = m_pModel->index(i,0);
           QString G0 = dIndex.data().toString();
           if(G0 != "")
           {
                text += G0 + " ";
           }
           dIndex = m_pModel->index(i,1);
           QString G1 = dIndex.data().toString();
           if(G1 != "")
           {
                text += G1 + " ";
           }
           dIndex = m_pModel->index(i,2);
           QString X = dIndex.data().toString();
           if(X != "")
           {
                text += X + " ";
           }
           dIndex = m_pModel->index(i,3);
           QString Y = dIndex.data().toString();
           if(Y != "")
           {
                text += Y + " ";
           }
           dIndex = m_pModel->index(i,4);
           QString Z = dIndex.data().toString();
           if(Z != "")
           {
                text += Z + " ";
           }

           textStream<<text<<endl;

           //
           text.remove(QRegExp("\\s"));
           m_commandList.append(text);
       }

       file.close();

       ui->lineEdit_filename->setText(fileName);

       QMessageBox::warning(this,"正确","保存G代码文件成功！");

     }
}

/**********************************************************************************/


void MainWindow::ReadGcodeReturn()
{
    while(GcodePort->canReadLine())
    {
        QString data = GcodePort->readLine().trimmed();

        if ((data == "ok") && (gcode_ok == false))
        {
            gcode_ok = true;
        }

        if (data[0] == '<')
        {
            // 更新机械坐标
            static QRegExp mpx("MPos:([^,]*),([^,]*),([^,^>^|]*)");
            if (mpx.indexIn(data) != -1)
            {
                //获取当前位置信息
                ui->label_coordX->setText(mpx.cap(1));
                ui->label_coordY->setText(mpx.cap(2));
                ui->label_coordZ->setText(mpx.cap(3));
            }

            //更新状态信息
            static QRegExp stx("<([^,^>^|]*)");
            if (stx.indexIn(data) != -1)
            {
                status = m_status.indexOf(stx.cap(1));
                if (status == -1) status = 0;
                if (status != laststatus)
                {
                    laststatus= status;
                    //ui->status_lable->setText(m_status[laststatus]);
                    ui->plainTextEdit_status->appendPlainText(laststatus + "\n");
                }
            }



        }
    }
}

void MainWindow::ReadCmdReturn()
{
    CmdPort->waitForReadyRead(10);
    QByteArray buf;
    buf = CmdPort->readAll();

    if (!buf.isEmpty())
    {
        if (buf[0] == 0x58)
        {
            //限位状态
            //getbit(buf[1], 2) == 1 ? (ui->label_limitX->setText("正常")) : (ui->label_limitX->setText("触发"));
            //getbit(buf[1], 0) == 1 ? (ui->label_limitY->setText("正常")) : (ui->label_limitY->setText("触发"));
            //getbit(buf[1], 1) == 1 ? (ui->label_limitZ->setText("正常")) : (ui->label_limitZ->setText("触发"));
            qDebug() << "number: " << buf.toHex().toUpper() << endl;
        }
        else if ((buf[0] == 0xAA) && ( buf.length() < 2))
        {
            //握手成功
        }
        else if ((buf[0] == 0xAA) && (buf.length() > 4))
        {
            //返回板子状态信息

        }
//        else if (buf[0])
    }

    buf.clear();
}

bool MainWindow::OpenPort(QString GcodePortName, QString CmdPortName, int GcodePortBaudReteValue, int CmdPortBaudReteValue)
{
    //oepn gcode send port
    GcodePort = new QSerialPort();
    GcodePort->setPortName(GcodePortName);
    if (!GcodePort->open(QIODevice::ReadWrite))
        return false;
    GcodePort->setBaudRate(GcodePortBaudReteValue);
    GcodePort->setDataBits(QSerialPort::Data8);
    GcodePort->setParity(QSerialPort::NoParity);
    GcodePort->setStopBits(QSerialPort::OneStop);
    GcodePort->setFlowControl(QSerialPort::NoFlowControl);

    // open communication port
    CmdPort = new QSerialPort();
    CmdPort->setPortName(CmdPortName);
    if (!CmdPort->open(QIODevice::ReadWrite))
        return false;
    CmdPort->setBaudRate(CmdPortBaudReteValue);
    CmdPort->setDataBits(QSerialPort::Data8);
    CmdPort->setParity(QSerialPort::NoParity);
    CmdPort->setStopBits(QSerialPort::OneStop);
    CmdPort->setFlowControl(QSerialPort::NoFlowControl);

    QObject::connect(GcodePort, SIGNAL(readyRead()), this, SLOT(ReadGcodeReturn()));
    QObject::connect(CmdPort, SIGNAL(readyRead()), this, SLOT(ReadCmdReturn()));
    QObject::connect(&StatusTimer, SIGNAL(timeout()), this, SLOT(GetStatusFun()));
    StatusTimer.start(10);
    return true;
}

bool MainWindow::SendGcode(QString message)
{
    return false;

    if (!GcodePort->isOpen())
        return false;
    if (!gcode_ok)
        return false;
    message = message.toUpper();
    GcodePort->write((message + "\r").toLatin1());
    gcode_ok = false;
    return true;
}

bool MainWindow::SendCmd(QString message)
{
    if (!CmdPort->isOpen())
    {
        qDebug() << "cmd port not open" << endl;
        return false;
    }
    CmdPort->write(QByteArray::fromHex(message.toLatin1().data()));
    return true;
}


void MainWindow::GetStatusFun()
{
    if (GcodePort->isOpen())
    {
        GcodePort->write(QByteArray(1, '?'));
    }
}

//解锁
void MainWindow::Unlock()
{
    GcodePort->write((QString("$X") + "\r").toLatin1());
}

void MainWindow::ChangePosition(int xp,int yp,int zp)
{
    if(xp != 0)
    {
        QRect rect = ui->label_YImage->geometry();
        int x = rect.x();
        int y = rect.y();
        int w = rect.width();
        int h = rect.height();
        ui->label_YImage->setGeometry(x+xp,y,w,h);

        rect = ui->label_ZImage->geometry();
        x = rect.x();
        y = rect.y();
        w = rect.width();
        h = rect.height();
        ui->label_ZImage->setGeometry(x+xp,y,w,h);

        rect = ui->label_ZRImage->geometry();
        x = rect.x();
        y = rect.y();
        w = rect.width();
        h = rect.height();

        ui->label_ZRImage->setGeometry(x+xp,y,w,h);
    }

    if(yp != 0)
    {
        QRect rect = ui->label_ZImage->geometry();
        int x = rect.x();
        int y = rect.y();
        int w = rect.width();
        int h = rect.height();

        ui->label_ZImage->setGeometry(x,y-yp,w,h);

        rect = ui->label_ZRImage->geometry();
        x = rect.x();
        y = rect.y();
        w = rect.width();
        h = rect.height();

        ui->label_ZRImage->setGeometry(x,y+yp,w,h);

    }

     if(zp != 0)
    {
         QRect rect = ui->label_ZRImage->geometry();
         int x = rect.x();
         int y = rect.y();
         int w = rect.width();
         int h = rect.height();

         ui->label_ZRImage->setGeometry(x+zp,y,w,h);
    }
}

void MainWindow::InitLoadImage()
{
   m_pXImage =  new QImage;
   m_pYImage =  new QImage;
   m_pZImage =  new QImage; //新建一个image对象
   m_pZRImage = new QImage;
   QString exeName = qApp->applicationDirPath();
   QString Xfilename =  exeName +"/XImage.png";
   QString Yfilename =  exeName +"/YImage.png";
   QString Zfilename =  exeName +"/ZImage.png";

   QString zrfilename = exeName +"/ZRImage.png";

   m_pXImage->load(Xfilename);  //加载图像
   m_pYImage->load(Yfilename);  //加载图像
   m_pZImage->load(Zfilename);  //加载图像
   m_pZRImage->load(zrfilename);

   ui->label_XImage->setPixmap(QPixmap::fromImage(*m_pXImage));
   ui->label_YImage->setPixmap(QPixmap::fromImage(*m_pYImage));
   ui->label_ZImage->setPixmap(QPixmap::fromImage(*m_pZImage));
   ui->label_ZRImage->setPixmap(QPixmap::fromImage(*m_pZRImage));

}

void MainWindow::Simulated()
{

}

void MainWindow::InitVideo()
{
    m_pVideoTimer = new QTimer(this);
    connect(m_pVideoTimer,SIGNAL(timeout()),this,SLOT(ReadFrame()));

    m_pCapture.open(0);

    m_pVideoTimer->start(40);
}

void MainWindow::ReadFrame()
{
    if(m_pCapture.isOpened())
    {

        Mat frame;
        m_pCapture.read(frame);

        QImage image = QImage((const uchar*)frame.data,frame.cols,frame.rows,QImage::Format_RGB888).rgbSwapped();

        ui->label_video->setPixmap(QPixmap::fromImage(image));    //  将图片显示到label上


    }


}

QString MainWindow::ByteArrayToHexString(QByteArray data){
    QString ret(data.toHex().toUpper());//转为16进制大写
    qDebug() << ret << endl;;
    int len = ret.length()/2;
    ret.insert(0,"0x");
    for(int i=1;i<len;i++)
    {
        ret.insert(4*i+i-1,",0x");//编写格式
    }
    return ret;
}



void MainWindow::BtnSimulatedClickedSlot()
{

    int indexCount = m_commandList.count();
    if(indexCount == 0)
    {
        return;
    }


    QModelIndex mIndex =  m_pModel->index(m_index ,0);
    ui->tableView->setCurrentIndex(mIndex);

    SendCommanLoop();

}

void MainWindow::OnModeButtonClicked(QAbstractButton *modeButton)
{
   if(ui->radioButton_at->isChecked())
   {
       m_bAutoMode = true;
   }
   else
   {
       m_bAutoMode = false;
   }
}

void MainWindow::BtnStopButtonClickedSlot()
{

}

void MainWindow::BtnPauseButtonClickedSlot()
{
   if(m_bRunStatus)
   {
      m_bRunStatus = false;
   }
   else
   {
      m_bRunStatus = true;
   }
}

void MainWindow::onTableClicked(const QModelIndex &index)
{
   if(index.isValid())
   {

      QModelIndex dIndex = m_pModel->index(index.row(),2);

      QString xStr = dIndex.data().toString();
      xStr = xStr.remove("X");

      dIndex = m_pModel->index(index.row(),3);
      QString yStr = dIndex.data().toString();
      yStr = yStr.remove("Y");

      dIndex = m_pModel->index(index.row(),4);
      QString zStr = dIndex.data().toString();
      zStr = zStr.remove("Z");


      ui->doubleSpinBox_X->setValue(xStr.toDouble());
      ui->doubleSpinBox_Y->setValue(yStr.toDouble());
      ui->doubleSpinBox_Z->setValue(zStr.toDouble());

   }
}

